package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.request.MetricCodeDictCreateReqDTO;
import com.huaxin.device.dto.request.MetricCodeDictPageListReqDTO;
import com.huaxin.device.dto.request.MetricCodeDictUpdateReqDTO;
import com.huaxin.device.mapper.MetricCodeDictMapper;
import com.huaxin.device.mapping.MetricCodeDictMapping;
import com.huaxin.device.models.MetricCodeDict;
import com.huaxin.device.service.MetricCodeDictService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class MetricCodeDictServiceImpl extends ServiceImpl<MetricCodeDictMapper, MetricCodeDict> implements MetricCodeDictService {

    private final ApplicationContext applicationContext;
    private final MetricCodeDictMapping mapping;
    private final MetricCodeDictMapper mapper;

    @Override
    public ResponseResult<MetricCodeDict> create(MetricCodeDictCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数为空");
        }

        // 校验 metricCode  是否已存在
        if (existsByFields(MetricCodeDict::getMetricCode, in.getMetricCode(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "指标编码已存在", null);
        }
        // 校验 metricName 是否已存在
        if (existsByFields(MetricCodeDict::getMetricName, in.getMetricName(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "指标名称已存在", null);
        }

        MetricCodeDict entity = mapping.toEntity(in);
        entity.setIsActive(entity.getIsActive() != null ? entity.getIsActive() : true); // 默认启用

        boolean saved = this.save(entity);
        if (!saved) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "保存失败", null);
        }

        return ResponseResult.ok(entity);
    }

    @Override
    public MetricCodeDict getByDictId(Integer id) {
        if (id == null) {
            throw new IllegalArgumentException("ID不能为空");
        }

        MetricCodeDict entity = this.getById(id);
        if (entity == null) {
            throw new IllegalArgumentException("记录不存在");
        }

        return entity;
    }

    @Override
    public ResponseResult<String> update(MetricCodeDictUpdateReqDTO in) {
        if (in == null || in.getId() == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        MetricCodeDict entity = this.getByDictId(in.getId());

        // 校验 metricName 是否已存在
        if (existsByFields(MetricCodeDict::getMetricName, in.getMetricName(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "指标名称已存在", null);
        }

        mapping.updateEntity(in, entity);

        boolean updated = this.updateById(entity);
        if (!updated) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "更新失败", null);
        }

        return ResponseResult.ok("更新成功");
    }

    @Override
    public ResponseResult<String> delete(Integer id) {
        MetricCodeDict entity = this.getByDictId(id);

        //TODO 可以增加业务约束，例如被引用则不可删
        boolean removed = this.applicationContext.getBean(MetricCodeDictService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败", null);
        }

        return ResponseResult.ok("删除成功！");
    }

    @Override
    public ResponseResult<String> active(Integer id) {
        return toggleStatus(id, true);
    }

    @Override
    public ResponseResult<String> inactive(Integer id) {
        return toggleStatus(id, false);
    }

    private ResponseResult<String> toggleStatus(Integer id, Boolean isActive) {
        MetricCodeDict entity = this.getById(id);
        if (entity == null) {
            return ResponseResult.failure(ResponseCode.NOT_FOUND, "记录不存在", null);
        }

        entity.setIsActive(isActive);

        if (!this.updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "操作失败", null);
        }

        return ResponseResult.ok(isActive ? "启用成功" : "禁用成功");
    }

    @Override
    public ResponseResult<IPage<MetricCodeDict>> pageQuery(MetricCodeDictPageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<MetricCodeDict> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<MetricCodeDict> wrapper = new LambdaQueryWrapper<>();

        if (hasText(in.getMetricCode())) {
            wrapper.like(MetricCodeDict::getMetricCode, in.getMetricCode());
        }
        if (hasText(in.getMetricName())) {
            wrapper.like(MetricCodeDict::getMetricName, in.getMetricName());
        }
        if (hasText(in.getCategory())) {
            wrapper.eq(MetricCodeDict::getCategory, in.getCategory());
        }
        if (hasText(in.getDataType())) {
            wrapper.eq(MetricCodeDict::getDataType, in.getDataType());
        }
        if (in.getIsActive() != null) {
            wrapper.eq(MetricCodeDict::getIsActive, in.getIsActive());
        }
        if (in.getAlarmEnabled() != null) {
            wrapper.eq(MetricCodeDict::getAlarmEnabled, in.getAlarmEnabled());
        }

        wrapper.orderByDesc(MetricCodeDict::getCreatedAt);
        IPage<MetricCodeDict> result = this.page(page, wrapper);

        return ResponseResult.ok(result);
    }

    /**
     * 检查多个字段值组合是否已存在（排除当前ID）
     *
     * @param fieldGetter 字段Getter
     * @param fieldValue  字段值
     * @param excludeId   要排除的ID（可为null）
     * @return 是否存在匹配记录
     */
    private boolean existsByFields(
            SFunction<MetricCodeDict, ?> fieldGetter,
            Object fieldValue,
            Integer excludeId) {

        if (fieldGetter == null) return false;

        LambdaQueryWrapper<MetricCodeDict> wrapper = new LambdaQueryWrapper<>();

        if (fieldValue == null ||
                (fieldValue instanceof CharSequence cs && cs.toString().trim().isEmpty())) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(fieldGetter)
                    .or().eq(fieldGetter, "")
            );
        } else {
            wrapper.eq(fieldGetter, fieldValue.toString().trim());
        }

        if (excludeId != null) {
            wrapper.ne(MetricCodeDict::getId, excludeId);
        }

        return this.count(wrapper) > 0;
    }
}